#pragma once
#include<string>
#include<pthread.h>
#include<vector>
#include<queue>


#define NUM 10

using namespace std;

//单例版线程池

struct ThreadInfo
{
    pthread_t tid;
    string name;
};

template<class T>
class Threadpool
{
public:
    void LOCK()
    {
        pthread_mutex_lock(&mutex);
    }
    void UNLOCK()
    {
        pthread_mutex_unlock(&mutex);
    }
    void Sleep()//进入等待
    {
        pthread_cond_wait(&cond,&mutex);
    }
    void WakeUp()//唤醒一个
    {
        pthread_cond_signal(&cond);
    }
    string Getname(pthread_t td)
    {
        for(auto ch:tids)
        {
            if(ch.tid==td){
                return ch.name;
            }
        }
        return "None";
    }
public:
     static void *HandlerTask(void *args)
     {
        Threadpool<T>* ts=static_cast< Threadpool<T>* >(args);//接收线程的信息
        while(true)
        {

            //如果这里直接Lock的话t，由于不是类内了，所以没办法调用类内的LOCK函数
            ts->LOCK();
            while(ts->EmptyTask())
            {
                ts->Sleep();//如果没有任务，则释放锁，并进入等待队列
            }
            T task=ts->pop();
            //如果有任务，则把任务拿出来            
            ts->UNLOCK();
            task();//处理任务
            //打印一下看一下结果是否符合
            //cout<<"run, "
            ///<<"result:"<<task.getresult()<<endl;
        }
     }
    static Threadpool<T>*GetInstance()
    {
        if(tp_==nullptr)//为什么要判断两次，为了提高效率，防止多个线程堵塞在这里
        {
            pthread_mutex_lock(&lock_);//这里还是会有可能有多个线程进入
            if(nullptr==tp_)
            {
                cout<<"log: singleton create done first!"<<endl;
                tp_=new Threadpool<T>();
            }
            pthread_mutex_unlock(&lock_);
        }
        return tp_;
    }
    void start(){
        int len=tids.size();
        for(int i =0;i<NUM;i++){
            tids[i].name="thread"+to_string(i);
            pthread_create(&(tids[i].tid),nullptr,HandlerTask,this);
        }

    }
    void push(const T& task)//有任务进来
    {
        LOCK();//这里加锁的原因是为了保证生产者在生产任务的时候，处于互斥关系
        task_.push(task);//进入新的任务
        //唤醒一个线程去处理
        WakeUp();
        UNLOCK();
    }
    T pop()
    {
        T task=task_.front();
        task_.pop();
        return task;

    }
     bool EmptyTask(){
        return task_.empty();
    }
private:
    Threadpool(int num=NUM){
        tids.resize(num);
        pthread_mutex_init(&mutex,nullptr);//初始化锁
        pthread_cond_init(&cond,nullptr);//初始化条件变量
    }
   ~Threadpool(){
        pthread_mutex_destroy(&mutex);
        pthread_cond_destroy(&cond);
    }
    Threadpool(const Threadpool<T>&)=delete;
    const Threadpool<T>& operator=(const Threadpool<T>&)=delete;
    vector<ThreadInfo>tids;//每个线程的信息
    queue<T>task_;//任务存放

    pthread_mutex_t mutex;//锁
    pthread_cond_t  cond;//条件变量

    static Threadpool<T>*tp_;
    static pthread_mutex_t lock_;
};
template<class T>
Threadpool<T>*Threadpool<T>::tp_=nullptr;
template<class T>
pthread_mutex_t Threadpool<T>::lock_=PTHREAD_MUTEX_INITIALIZER;
